home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 2001 May / SGI Freeware 2001 May - Disc 1.iso / dist / fw_mysql.idb / usr / freeware / share / sql-bench / copy-db.z / copy-db
Encoding:
Text File  |  1999-10-18  |  8.8 KB  |  356 lines

  1. #!/bin/perl5
  2. ####
  3. #### start initialition
  4. ####
  5.  
  6. $VER = "1.0";
  7.  
  8. use Getopt::Long;
  9. use DBI;
  10.  
  11. $max_row_length=500000;        # Don't create bigger SQL rows that this
  12. $opt_lock=1;            # lock tables
  13.  
  14. chomp($pwd = `pwd`); $pwd = "." if ($pwd eq '');
  15.  
  16. require "$pwd/server-cfg" || die "Can't read Configuration file: $!\n";
  17.  
  18. $|=1;
  19.  
  20. $opt_from_server= $opt_to_server= "mysql";
  21. $opt_from_host= $opt_to_host=     "localhost";
  22. $opt_from_db= $opt_to_db=         "test";
  23. $opt_from_user=$opt_from_password=$opt_to_user=$opt_to_password="";
  24. $opt_help=$opt_verbose=$opt_debug=0;
  25.  
  26.  
  27. GetOptions("from-server=s","to-server=s","from-host=s","to-host=s","from-db=s",
  28.        "to-db=s", "help", "verbose","debug") || usage();
  29.  
  30. usage() if ($opt_help || 
  31.         ($opt_from_server eq $opt_to_server && 
  32.          $opt_from_db eq $opt_to_db &&
  33.          $opt_from_host eq $opt_to_host));
  34.  
  35. ####
  36. #### Usage
  37. ####
  38.  
  39.  
  40. sub usage
  41. {
  42.   print <<EOF;
  43.  
  44. $0 version $VER by Monty
  45.  
  46.  Copies tables between two database servers. If the destination table doesn\'t
  47.  exist it\'s autoamticly created.  If the destination table exists, it
  48.  should be compatible with the source table.
  49.  
  50.  Because DBI doesn\'t provide full information about the columns in a table,
  51.  some columns may not have optimal types in a create tables.  Any created
  52.  tables will also not have any keys!
  53.  
  54.   Usage: $0 [options] tables...
  55.  
  56.   Options:
  57.   --help         Show this help and exit
  58.   --from-server      Source server            (Default: $opt_from_server)
  59.   --from-host     Source hostname        (Default: $opt_from_host)
  60.   --from-db       Source database name        (Default: $opt_from_db)
  61.   --from-user      Source user            (Default: $opt_from_password)
  62.   --from-password Source password        (Default: $opt_from_password)
  63.   --to-server     Destination server        (Default: $opt_to_server)
  64.   --to-host       Destination hostname        (Default: $opt_to_host)
  65.   --to-db         Destination database name    (Default: $opt_to_db)
  66.   --to-user      Destination user        (Default: $opt_to_user)
  67.   --to-password      Destination password        (Default: $opt_to_password)
  68.   --verbose      Be more verbose
  69.  
  70.   If you the server names ends with _ODBC, then this program will connect
  71.   through ODBC instead of using a native driver.
  72. EOF
  73.    exit(0);
  74. }
  75.  
  76. ####
  77. #### Connect
  78. ####
  79.  
  80. $from_server=get_server($opt_from_server,$opt_from_host,$opt_from_db);
  81. $to_server=get_server($opt_to_server,$opt_to_host,$opt_to_db);
  82.  
  83. $opt_user=$opt_from_user; $opt_password=$opt_from_password;
  84. print "- connecting to SQL servers\n" if ($opt_verbose);
  85. $from_dbh=$from_server->connect() || die "Can't connect to source server $opt_from_server on host $opt_from_host using db $opt_from_db";
  86. $opt_user=$opt_to_user; $opt_password=$opt_to_password;
  87. $to_dbh=$to_server->connect() || die "Can't connect to source server $opt_to_server on host $opt_to_host using db $opt_to_db";
  88.  
  89. ####
  90. #### Copy data
  91. ####
  92.  
  93. foreach $table (@ARGV)
  94. {
  95.  
  96.   print "- querying $table\n" if ($opt_verbose);
  97.   $sth=$from_dbh->prepare("select * from $table") || die "Can't prepare query to get $table; $DBI::errstr";
  98.   $sth->execute || die "Can't execute query to get data from $table; $DBI::errstr";
  99.  
  100.   if (!table_exists($to_server,$to_dbh,$table))
  101.   {
  102.     print "- creating $table\n" if ($opt_verbose);
  103.     $table_def=get_table_definition($from_server,$from_dbh,$sth);
  104.     do_many($to_dbh,$to_server->create($table,$table_def,[]));
  105.   }
  106.   if ($opt_lock && $to_server->{'lock_tables'})
  107.   {
  108.     print "- locking $table\n" if ($opt_verbose);
  109.     $to_dbh->do("lock tables $table WRITE");
  110.   }
  111.  
  112.   $columns=$sth->{NUM_OF_FIELDS};
  113.   $columns_to_quote=get_columns_to_quote($sth);
  114.   $multi_value_insert=$sth->{'multi_value_insert'};
  115.   $query="insert into $table values"; $result="";
  116.  
  117.   print "- copying $table\n" if ($opt_verbose);
  118.   while (($row = $sth->fetchrow_arrayref))
  119.   {
  120.     $tmp="(";
  121.     for ($i=0 ; $i < $columns ; $i++)
  122.     {
  123.       if ($columns_to_quote->[$i])
  124.       {
  125.     $tmp.= $to_dbh->quote($row->[$i]) . ",";
  126.       }
  127.       else
  128.       {
  129.     $tmp.= $row->[$i] . ",";    
  130.       }
  131.     }
  132.     substr($tmp,-1)=")";        # Remove last ','
  133.     if ($multi_value_insert)
  134.     {
  135.       $to_dbh->do($query . $tmp) || die "Can't insert row: $DBI::errstr";
  136.     }
  137.     elsif (length($result)+length($tmp) >= $max_row_length && $result)
  138.     {
  139.       $to_dbh->do($query . $result) || die "Can't insert row: $DBI::errstr";
  140.       $result="";
  141.     }
  142.     elsif (length($result))
  143.     {
  144.       $result.= ",$tmp";
  145.     }
  146.     else
  147.     {
  148.       $result=$tmp;
  149.     }
  150.   }
  151.   if (length($result))
  152.   {
  153.     $to_dbh->do($query . $result) || die "Can't insert row: $DBI::errstr";
  154.   }
  155.   if ($opt_lock && $to_server->{'lock_tables'})
  156.   {
  157.     $to_dbh->do("unlock tables");
  158.   }
  159. }
  160.  
  161.  
  162. sub get_table_definition
  163. {
  164.   my ($server,$dbh,$sth)=@_;
  165.   my ($i,$names,$types,$scale,$precision,$nullable,@res);
  166.  
  167.   $names=$sth->{NAME};
  168.   $types=$sth->{TYPE};
  169.   $nullable=$sth->{NULLABLE};
  170.   if (0)
  171.   {
  172.     # The following doesn't yet work
  173.     $scale=$sth->{SCALE};
  174.     $precision=$sth->{PRECISION};
  175.   }
  176.   else
  177.   {
  178.     my (@tmp);
  179.     @tmp= (undef()) x $sth->{NUM_OF_FIELDS};
  180.     $precision= $scale= \@tmp;
  181.   }
  182.   for ($i = 0; $i < $sth->{NUM_OF_FIELDS} ; $i++)
  183.   {
  184.     push(@res,$names->[$i] . " " .
  185.      odbc_to_sql($server,$types->[$i],$precision->[$i],$scale->[$i]) .
  186.      ($nullable->[$i] ? "" : " NOT NULL"));
  187.   }
  188.   return \@res;
  189. }
  190.  
  191.  
  192. sub odbc_to_sql
  193. {
  194.   my ($server,$type,$precision,$scale)=@_;
  195.  
  196.   if ($type == DBI::SQL_CHAR())
  197.   {
  198.     return defined($precision) ? "char($precision)" : "varchar(255)";
  199.   }
  200.  
  201.   if ($type == DBI::SQL_NUMERIC())
  202.   {
  203.     $precision=15 if (!defined($precision));
  204.     $scale=6 if (!defined($scale));
  205.     return "numeric($precision,$scale)";
  206.   }
  207.   if ($type == DBI::SQL_DECIMAL())
  208.   {
  209.     $precision=15 if (!defined($precision));
  210.     $scale=6 if (!defined($scale));
  211.     return "decimal($precision,$scale)";
  212.   }
  213.   if ($type == DBI::SQL_INTEGER())
  214.   {
  215.     return "integer" if (!defined($precision));
  216.     return "integer($precision)";
  217.   }
  218.   if ($type == DBI::SQL_SMALLINT())
  219.   {
  220.     return "smallint" if (!defined($precision));
  221.     return "smallint($precision)";
  222.   }
  223.   if ($type == DBI::SQL_FLOAT())
  224.   {
  225.     $precision=12 if (!defined($precision));
  226.     $scale=2 if (!defined($scale));
  227.     return "float($precision,$scale)";
  228.   }
  229.   if ($type == DBI::SQL_REAL())
  230.   {
  231.     $precision=12 if (!defined($precision));
  232.     $scale=2 if (!defined($scale));
  233.     return "float($precision,$scale)";
  234.   }
  235.   if ($type == DBI::SQL_DOUBLE())
  236.   {
  237.     $precision=22 if (!defined($precision));
  238.     $scale=2 if (!defined($scale));
  239.     return "double($precision,$scale)";
  240.   }
  241.   if ($type == DBI::SQL_VARCHAR())
  242.   {
  243.     $precision=255 if (!defined($precision));
  244.     return "varchar($precision)";
  245.   }
  246.   return "date"                if ($type == DBI::SQL_DATE());
  247.   return "time"                if ($type == DBI::SQL_TIME());
  248.   return "timestamp"            if ($type == DBI::SQL_TIMESTAMP());
  249.   return $server->{'text'}        if ($type == DBI::SQL_LONGVARCHAR());
  250.   return $server->{'blob'}        if ($type == DBI::SQL_LONGVARBINARY());
  251.   if ($type == DBI::SQL_BIGINT())
  252.   {
  253.     return "bigint" if (!defined($precision));
  254.     return "bigint($precision)";
  255.   }
  256.   if ($type == DBI::SQL_TINYINT())
  257.   {
  258.     return "tinyint" if (!defined($precision));
  259.     return "tinyint($precision)";
  260.   }
  261.   die "Can't covert type '$type' to a ODBC type\n";
  262. }
  263.  
  264. #
  265. # return an array with 1 for all coumns that we have to quote
  266. #
  267.                           
  268. sub get_columns_to_quote($sth)
  269. {
  270.   my ($sth)=@_;
  271.   my ($i,@res,$type,$tmp);
  272.  
  273.   @res=();
  274.   for ($i = 0; $i < $sth->{NUM_OF_FIELDS} ; $i++)
  275.   {
  276.     $type=$sth->{TYPE}->[$i];
  277.     $tmp=1;            # String by default
  278.     if ($type == DBI::SQL_NUMERIC()    || $type == DBI::SQL_DECIMAL() ||
  279.     $type == DBI::SQL_INTEGER()    || $type == DBI::SQL_SMALLINT() ||
  280.     $type == DBI::SQL_SMALLINT()    || $type == DBI::SQL_FLOAT() ||
  281.     $type == DBI::SQL_REAL()     || $type == DBI::SQL_DOUBLE() ||
  282.     $type == DBI::SQL_BIGINT()    || $type == DBI::SQL_TINYINT())
  283.     {
  284.       $tmp=0;
  285.     }
  286.     push (@res,$tmp);
  287.   }
  288.   return \@res;
  289. }
  290.  
  291. #
  292. # Check if table exists;  Return 1 if table exists
  293. #
  294.  
  295. sub table_exists
  296. {
  297.   my ($server,$dbh,$table)=@_;
  298.   if ($server->{'limits'}->{'group_functions'})
  299.   {
  300.     return !safe_query($dbh,"select count(*) from $table");
  301.   }
  302.   if ($server->{'limits'}->{'limit'})
  303.   {
  304.     return !safe_query($dbh,"select * from $table limit 1");
  305.   }
  306.   die "Don't know how to check if table '$table' exists in destination server\n";
  307. }
  308.  
  309.  
  310. #
  311. # execute query;  return 0 if query is ok
  312. #
  313.  
  314. sub safe_query
  315. {
  316.   my ($dbh,$query)=@_;
  317.   my ($sth);
  318.  
  319.   print "query: $query\n" if ($opt_debug);
  320.   if (!($sth= $dbh->prepare($query)))
  321.   {
  322.     print "error: $DBI::errstr\n" if ($opt_debug);
  323.     return 1;
  324.   }
  325.   if (!$sth->execute)
  326.   {
  327.     print "error: $DBI::errstr\n" if ($opt_debug);
  328.     return 1
  329.   }
  330.   while ($sth->fetchrow_arrayref)
  331.   {
  332.   }
  333.   $sth->finish;
  334.   undef($sth);
  335.   return 0;
  336. }
  337.  
  338. #
  339. # execute an array of queries
  340. #
  341.  
  342. sub do_many
  343. {
  344.   my ($dbh,@statements)=@_;
  345.   my ($statement,$sth);
  346.  
  347.   foreach $statement (@statements)
  348.   {
  349.     print "query: $statement\n" if ($opt_debug);
  350.     if (!($sth=$dbh->do($statement)))
  351.     {
  352.       die "Can't execute command '$statement'\nError: $DBI::errstr\n";
  353.     }
  354.   }
  355. }
  356.